package map.core.util;

import org.geotools.api.referencing.FactoryException;
import org.geotools.api.referencing.crs.CoordinateReferenceSystem;
import org.geotools.api.referencing.operation.MathTransform;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;

public class MercatorUtil {

    public static void main(String[] args) {


        int tileSize = 5120;
        System.out.println(getWebMercatorBox(0, 0, 0, tileSize));
        System.out.println(getGeographyBox(0, 0, 0, tileSize));

        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                System.out.println("level=" + 1 + ",row=" + i + ",column=" + j);
                System.out.println(getWebMercatorBox(1, i, j, tileSize));
                System.out.println(getGeographyBox(1, i, j, tileSize));
            }
        }


        //System.out.println(getWebMercatorBox(1, 1, 1, 5120));
        // System.out.println(getGeographyBox(1, 1, 1, 5120));
    }

    static MathTransform transform;


    /**
     * 4326 to 3857
     * @return
     */
    static MathTransform getMathTransform() {
        if (transform != null) {
            return transform;
        } else {

            try {
                CoordinateReferenceSystem from = CRS.decode("EPSG:3857");
                CoordinateReferenceSystem to = CRS.decode("EPSG:4326");
                transform = CRS.findMathTransform(from, to);
            } catch (FactoryException e) {
                e.printStackTrace();
            }
            return transform;
        }

    }

    /**
     * @param lonlatEnvelope WGS84
     * @param zoom
     * @return [minRow,maxRow,minColumn,maxColumn]
     */
    public static int[] getRowAndColumnsBounds(Envelope lonlatEnvelope, int zoom){
        Envelope mercatorEnvelope = CRSHelper.lonLat2WebMercator(lonlatEnvelope);
        double resolution = resolutions[zoom];
        int tileSize = 256;
        double tileWidthInMeter = resolution * tileSize;

        int minTileIndex = 0;
        int maxTileIndex = (int) Math.pow(2,zoom)-1;




        int minColumn = (int) Math.floor((mercatorEnvelope.getMinX()-origin[0])/tileWidthInMeter);
        int maxColumn = (int) Math.ceil((mercatorEnvelope.getMaxX()-origin[0])/tileWidthInMeter);

        int minRow = (int) Math.floor((origin[1]-mercatorEnvelope.getMaxY())/tileWidthInMeter);
        int maxRow = (int) Math.ceil((origin[1]-mercatorEnvelope.getMinY())/tileWidthInMeter);

        minRow = Math.max(minRow,minTileIndex);
        maxRow = Math.min(maxRow,maxTileIndex);
        minColumn = Math.max(minColumn,minTileIndex);
        maxColumn = Math.min(maxColumn,maxTileIndex);

        return new int[]{minRow,maxRow,minColumn,maxColumn};

    }



    public static Envelope getGeographyBox(int level, int row, int column, int tileSize) {
        Envelope envelope = MercatorUtil.getWebMercatorBox(level, row, column, tileSize);
        Coordinate leftBottom = new Coordinate(envelope.getMinX(), envelope.getMinY());
        Coordinate rightTop = new Coordinate(envelope.getMaxX(), envelope.getMaxY());

        return new Envelope(CRSHelper.webMercatorToLonLat(leftBottom), CRSHelper.webMercatorToLonLat(rightTop));
    }

    public static Envelope getWebMercatorBox(int level, int row, int column, int tileSize) {

        tileSize = 256;

        double resolution = resolutions[level];
        double tileWidthInMeter = resolution * tileSize;



        double minX = column * tileWidthInMeter + origin[0];
        double maxX = minX + tileWidthInMeter;
        double maxY = origin[1] -  row * tileWidthInMeter ;
        double minY = maxY - tileWidthInMeter;
        Envelope envelope = new Envelope(minX , maxX, minY, maxY);
        return envelope.intersection(maxEnvelope);
    }


    public static Envelope maxEnvelope = new Envelope(-2.003750834E7,  2.003750834E7, -2.003750834E7,  2.003750834E7);
    static double[] origin = {-20037508,20037508};



    static double[] resolutions = {
            156543.03390625,
            78271.516953125,
            39135.7584765625,
            19567.87923828125,
            9783.939619140625,
            4891.9698095703125,
            2445.9849047851562,
            1222.9924523925781,
            611.4962261962891,
            305.74811309814453,
            152.87405654907226,
            76.43702827453613,
            38.218514137268066,
            19.109257068634033,
            9.554628534317017,
            4.777314267158508,
            2.388657133579254,
            1.194328566789627,
            0.5971642833948135,
            0.2985821416974068,
            0.1492910708487034,
            0.0746455354243517,
            0.0373227677121758,
            0.0186613838560879,
            0.009330691928044
    };


}
